
package ar.com.lemil.j2me.serialization;

import java.io.*;
import java.util.Enumeration;
import java.util.Hashtable;


public class ObjectOutputSream extends OutputStream
    implements IObjectOutputStream
{

    public ObjectOutputSream(OutputStream outputstream)
    {
        classCode = 80;
        out = outputstream;
    }

    public void writeObject(Object obj)
        throws IOException
    {
        if(obj == null)
            throw new IOException("Object is null");
        if(!(obj instanceof ISerializable))
            throw new IOException("Object is't implement ISerializable interface.");
        data.write(10);
        String s = obj.getClass().getName();
        Object obj1 = classCache.get(s);
        if(obj1 == null)
        {
            classCache.put(s, new Byte(classCode));
            writeByte(classCode);
            classCode++;
        } else
        {
            writeByte(((Byte)obj1).byteValue());
        }
        ((ISerializable)obj).writeObject(this);
    }

    public void writeByte(byte byte0)
        throws IOException
    {
        data.write(byte0);
    }

    public void writeChar(char c)
        throws IOException
    {
        data.write(c >>> 8);
        data.write(c);
    }

    public void writeShort(short word0)
        throws IOException
    {
        data.write(word0 >>> 8);
        data.write(word0);
    }

    public void writeInt(int i)
        throws IOException
    {
        data.write(i >>> 24);
        data.write(i >>> 16);
        data.write(i >>> 8);
        data.write(i);
    }

    public void writeLong(long l)
        throws IOException
    {
        data.write((byte)(int)(l >>> 56));
        data.write((byte)(int)(l >>> 48));
        data.write((byte)(int)(l >>> 40));
        data.write((byte)(int)(l >>> 32));
        data.write((byte)(int)(l >>> 24));
        data.write((byte)(int)(l >>> 16));
        data.write((byte)(int)(l >>> 8));
        data.write((byte)(int)l);
    }

    public void writeASC(String s)
        throws IOException
    {
        if(s == null || s.length() == 0)
        {
            data.write(0);
            return;
        }
        int i = s.length();
        if(i > 65535)
            throw new IOException("writeASC(): Value too large");
        data.write(i >>> 8);
        data.write(i);
        for(int j = 0; j < i; j++)
        {
            char c = s.charAt(j);
            if(c > '\177')
                throw new IOException("Unsupported ASC char " + (int)c);
            data.write(c);
        }

    }

    public void writeShortASC(String s)
        throws IOException
    {
        if(s == null || s.length() == 0)
        {
            data.write(0);
            return;
        }
        int i = s.length();
        if(i > 127)
            throw new IOException("writeShortASC(): Value too large");
        data.write(i);
        for(int j = 0; j < i; j++)
        {
            char c = s.charAt(j);
            if(c > '\177')
                throw new IOException("Unsupported ASC char " + (int)c);
            data.write(c);
        }

    }

    public void writeUTF(String s)
        throws IOException
    {
        if(s == null || s.length() == 0)
        {
            data.write(0);
            return;
        }
        byte abyte0[] = s.getBytes("utf-8");
        int i = abyte0.length;
        if(i > 65535)
            throw new IOException("writeUTF(): Value too large");
        data.write(i >>> 8);
        data.write(i);
        for(int j = 0; j < i; j++)
            data.write(abyte0[j]);

    }

    public void writeShortUTF(String s)
        throws IOException
    {
        if(s == null || s.length() == 0)
        {
            data.write(0);
            return;
        }
        byte abyte0[] = s.getBytes("utf-8");
        int i = abyte0.length;
        if(i > 127)
            throw new IOException("writeShortUTF(): Value too large");
        data.write(i);
        for(int j = 0; j < i; j++)
            data.write(abyte0[j]);

    }

    public void write(int i)
        throws IOException
    {
        data.write(i);
    }

    public void flush()
        throws IOException
    {
        if(flushed)
            return;
        ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream();
        bytearrayoutputstream.write(IConstants.HEADER);
        int i = classCache.size();
        bytearrayoutputstream.write(i);
        for(Enumeration enumeration = classCache.keys(); enumeration.hasMoreElements();)
        {
            String s = (String)enumeration.nextElement();
            byte byte0 = ((Byte)classCache.get(s)).byteValue();
            bytearrayoutputstream.write(byte0);
            int j = s.length();
            bytearrayoutputstream.write(j);
            int k = 0;
            while(k < j) 
            {
                bytearrayoutputstream.write(s.charAt(k));
                k++;
            }
        }

        byte abyte0[] = bytearrayoutputstream.toByteArray();
        byte abyte1[] = data.toByteArray();
        byte abyte2[] = new byte[abyte0.length + abyte1.length];
        System.arraycopy(abyte0, 0, abyte2, 0, abyte0.length);
        System.arraycopy(abyte1, 0, abyte2, abyte0.length, abyte1.length);
        out.write(abyte2);
        out.flush();
        flushed = true;
    }

    public void close()
        throws IOException
    {
        if(!flushed)
            flush();
        out.close();
    }

    public void writeBytes(byte abyte0[])
        throws IOException
    {
        int i = abyte0.length;
        writeInt(i);
        for(int j = 0; j < i; j++)
            data.write(abyte0[j]);

    }

    public void writeBoolean(boolean flag)
        throws IOException
    {
        if(flag)
            data.write(1);
        else
            data.write(0);
    }

    public void writeInts(int ai[])
        throws IOException
    {
        int i = ai.length;
        writeInt(i);
        for(int j = 0; j < i; j++)
            writeInt(ai[j]);

    }

    private final OutputStream out;
    private final ByteArrayOutputStream data = new ByteArrayOutputStream();
    private final Hashtable classCache = new Hashtable(3);
    private byte classCode;
    private boolean flushed;
}
